package org.jheuristics.ga.operators;

import java.io.Serializable;

import org.epanetgrid.otimizacao.log.AGLogger;
import org.epanetgrid.otimizacao.util.OtimizacaoUtil;
import org.jheuristics.Individual;
import org.jheuristics.ga.DefaultPopulation;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.operators.selectors.RandomSelector;


/**
 * TODO
 *
 * @author Marcell Manfrin, marcell@ourgrid.org, Jan 9, 2006
 */
public class TournamentReproductionOperator extends AbstractReproductionOperator implements Serializable {
	private PopulationChooser fromPopChooser;
	private PopulationChooser toPopChooser;
	private boolean cleanAfterFromPop;
	private boolean cleanBeforeToPop;

	/**
	 * TODO
	 *
	 * @param rate
	 * @param selector
	 * @param reproductor
	 * @param fromPopChooser
	 * @param cleanAfterFromPop
	 * @param toPopChooser
	 * @param cleanBeforeToPop
	 */
	public TournamentReproductionOperator(Rate rate, Selector selector, Reproductor reproductor, PopulationChooser fromPopChooser, boolean cleanAfterFromPop, PopulationChooser toPopChooser, boolean cleanBeforeToPop) {
		super(rate, selector, reproductor);
		if (null == fromPopChooser) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		if (null == toPopChooser) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		this.fromPopChooser = fromPopChooser;
		this.toPopChooser = toPopChooser;
		this.cleanAfterFromPop = cleanAfterFromPop;
		this.cleanBeforeToPop = cleanBeforeToPop;
	}

	/**
	 * TODO
	 *
	 * @param status
	 * @param config
	 * @see org.jheuristics.ga.Operator#operate(org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public void operate(GAStatus status, GAConfig config) {
		Population fromPop = fromPopChooser.choose(status, config);
		Population toPop = toPopChooser.choose(status, config);
		Population reproductedIndividuals = reproduce(fromPop, status, config);
		if (cleanAfterFromPop) {
			fromPop.clear();
		}
		if (cleanBeforeToPop) {
			toPop.clear();
		}
		toPop.addIndividuals(reproductedIndividuals);
	}

	@Override
	protected Population reproduce(Population population, GAStatus status, GAConfig config) {
		 Selector selector = getSelector();
		 Reproductor reproductor = getReproductor();
		 int rate = getRate().rate(status, config);
		 
		 Population result = new DefaultPopulation();
		 DefaultPopulation selectedPopulation = new DefaultPopulation();
		 selectedPopulation.addIndividuals(selector.select(population, rate, status, config));
		 RandomSelector randomSelector = new RandomSelector();
		 
		 for (int i = 0; i < rate; i++) {
			 result.addIndividuals(reproductor.reproduce(randomSelector.select(selectedPopulation, 2, status, config), status, config));
		 }
		 
		 StringBuffer buffer = new StringBuffer("\nResultado da reprodução: \n");
		 buffer.append(OtimizacaoUtil.format(result));
//	        Individual[] ind = result.toIndividualArray();
//	        for (int i = 0; i < ind.length; i++) {
//				buffer.append(ind[i]);
//				buffer.append("\n");
//			}
	        AGLogger.getInstance().debug(buffer);
		 
		 return result;
	}

}
